package com.xhtt.modules.task.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhtt.common.exception.RRException;
import com.xhtt.common.utils.CopyUtils;
import com.xhtt.common.utils.PageUtils;
import com.xhtt.common.utils.Query;
import com.xhtt.modules.msg.entity.MsgInfo;
import com.xhtt.modules.msg.service.MsgInfoService;
import com.xhtt.modules.msg.service.MsgUserService;
import com.xhtt.modules.sys.entity.SysDeptEntity;
import com.xhtt.modules.sys.entity.SysUserEntity;
import com.xhtt.modules.sys.service.SysDeptService;
import com.xhtt.modules.sys.service.SysUserService;
import com.xhtt.modules.task.dao.TaskServiceTaskMapper;
import com.xhtt.modules.task.entity.TaskOperTask;
import com.xhtt.modules.task.entity.TaskServicePlan;
import com.xhtt.modules.task.entity.TaskServiceTask;
import com.xhtt.modules.task.model.TaskOperModel;
import com.xhtt.modules.task.model.msg.PlanTaskModel;
import com.xhtt.modules.task.model.service.ArrangeModel;
import com.xhtt.modules.task.model.service.TaskServiceOtherModel;
import com.xhtt.modules.task.model.ship.WorkUserModel;
import com.xhtt.modules.task.service.TaskServicePlanService;
import com.xhtt.modules.task.service.TaskServiceTaskService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 罐任务-任务分配计划 服务实现类
 * </p>
 *
 * @author feipc
 * @since 2019-03-11
 */
@Service
public class TaskServiceTaskServiceImpl extends ServiceImpl<TaskServiceTaskMapper, TaskServiceTask> implements TaskServiceTaskService {
    @Autowired
    private TaskServicePlanService taskServicePlanService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysDeptService sysDeptService;
    @Resource
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private MsgInfoService msgInfoService;
    @Autowired
    private MsgUserService msgUserService;

    @Override
    public ArrangeModel getTaskDetail(Integer planId, SysUserEntity user) {
        ArrangeModel sm = new ArrangeModel();
        TaskServicePlan servicePlan = taskServicePlanService.getById(planId);
        if (null == servicePlan) {
            throw new RRException("对象不存在");
        }
        sm.setPlanId(planId);
        sm.setMainTaskName(servicePlan.getTaskName());
        List<TaskServiceTask> taskList = this.list(new LambdaQueryWrapper<TaskServiceTask>().eq(TaskServiceTask::getServicePlanId, planId));
        if (servicePlan.getStatus().intValue() == 2)//如果在待分配状态下，就只能看自己组的任务数据
        {
            //过滤下任务列表
            taskList.removeIf(t -> (null == t.getExecTeamId() || t.getExecTeamId().intValue() != user.getTeamId().intValue()));
        }
        for (TaskServiceTask task : taskList) {
            if (null == task.getIfConfirm()) {
                task.setIfConfirm(0);//默认设置0
            }
            if (null == task.getIfPhoto()) {
                task.setIfPhoto(0);//默认设置0
            }
            if (null != task.getUserMainId()) {
                SysUserEntity u = sysUserService.getOne(new LambdaQueryWrapper<SysUserEntity>().eq(SysUserEntity::getUserId, task.getUserMainId()).select(SysUserEntity::getUserId, SysUserEntity::getName));
                task.setUserMainName(u.getName());
            }
            if (null != task.getExecTeamId()) {
                SysDeptEntity dept = sysDeptService.getOne(new LambdaQueryWrapper<SysDeptEntity>().eq(SysDeptEntity::getDeptId, task.getExecTeamId()));
                task.setExecTeamName(dept.getName());
            }
            if (null != task.getConfirmUser()) {
                SysUserEntity u = sysUserService.getOne(new LambdaQueryWrapper<SysUserEntity>().eq(SysUserEntity::getUserId, task.getConfirmUser()).select(SysUserEntity::getUserId, SysUserEntity::getName));
                task.setConfirmUserName(u.getName());
            }
        }
        sm.setTasks(taskList);
        return sm;
    }

    @Override
    public void pubTask(List<TaskServiceTask> tasks, SysUserEntity user) {
        List<TaskServiceTask> dbs = new ArrayList<>();
        TaskServiceTask db;
        Integer planId = 0;
        List<Integer> thisIds = new ArrayList<>();//
        for (TaskServiceTask taskServiceTask : tasks) {
            thisIds.add(taskServiceTask.getId());
            if (CollectionUtils.isNotEmpty(taskServiceTask.getUserAssistModel())) {
                taskServiceTask.setUserAssist(JSON.toJSONString(taskServiceTask.getUserAssistModel()));
            } else {
                taskServiceTask.setUserAssist(JSON.toJSONString(Collections.EMPTY_LIST));
            }
            db = this.getById(taskServiceTask.getId());
            CopyUtils.copyProperties(taskServiceTask, db);
            db.setStatus(4);
            db.setPubTime(LocalDateTime.now());
            //判断下是不是有确认人，因为除了管线任务会手动设置 其他任务要默认选某组的组长（选了需要确认的话）
            if (null == db.getConfirmUser() && db.getIfConfirm().intValue() == 1) {
                db.setConfirmUserName(user.getName());
                db.setConfirmUser(user.getUserId().intValue());
            }
            dbs.add(db);
            planId = taskServiceTask.getServicePlanId();
        }
        this.updateBatchById(dbs);
        //更新主任务状态为4
        //如果这个主任务的所有子任务都被分配完了 那就更新主任务状态为4
        int count = this.count(new LambdaQueryWrapper<TaskServiceTask>().eq(TaskServiceTask::getServicePlanId, planId).
                and(qw -> qw.eq(TaskServiceTask::getStatus, 0).or(qw2 -> qw2.eq(TaskServiceTask::getStatus, 2)))
                .notIn(TaskServiceTask::getId, thisIds));
        if (count == 0) {
            TaskServicePlan plan = new TaskServicePlan();
            plan.setId(planId);
            plan.setStatus(4);
            taskServicePlanService.updateById(plan);
        }

        //发消息
        taskExecutor.submit(() -> {
            List<MsgInfo> msgList = new ArrayList<>();
            for (TaskServiceTask serviceTask : dbs) {
                PlanTaskModel ptm = new PlanTaskModel(serviceTask.getId(), serviceTask.getMainTaskName(), serviceTask.getName(), "", serviceTask.getTaskStartDate(), serviceTask.getUserAssistModel());

                Set<Integer> userIds = new HashSet<>();
                MsgInfo msg = new MsgInfo("计划任务", "维修任务:" + serviceTask.getMainTaskName(), "任务待完成提交", JSON.toJSONString(ptm));
                userIds.add(serviceTask.getUserMainId());
                msg.setUserIdList(userIds);
                msgList.add(msg);
            }
            msgInfoService.saveMsgBatch(msgList);
        });
    }

    @Override
    @Transactional
    public void pubTempTask(TaskServicePlan servicePlan) {
        TaskServiceTask task = servicePlan.getTaskServiceTask();
        servicePlan.setType(9);//9 临时任务
        servicePlan.setTaskName(task.getName());
        servicePlan.setStatus(4);//直接进入现场作业阶段
        servicePlan.setPlanStartDate(task.getTaskStartDate());
        taskServicePlanService.save(servicePlan);

        task.setServicePlanId(servicePlan.getId());
        task.setStatus(4);//直接进入现场作业阶段
        task.setType(99);//其他 页面没有设置类型的地方
        task.setPubTime(LocalDateTime.now());
        if (CollectionUtils.isNotEmpty(task.getUserAssistModel())) {
            task.setUserAssist(JSON.toJSONString(task.getUserAssistModel()));
        } else {
            task.setUserAssist(JSON.toJSONString(Collections.EMPTY_LIST));
        }

        //type
        //判断下是不是有确认人，因为除了管线任务会手动设置 其他任务要默认选某组的组长（选了需要确认的话）
        if (task.getIfConfirm().intValue() == 1) {
            String str = MDC.get("user");
            if (StringUtils.isNotEmpty(str)) {
                SysUserEntity user = JSON.parseObject(str, SysUserEntity.class);
                task.setConfirmUserName(user.getName());
                task.setConfirmUser(user.getUserId().intValue());
            }
        }

        this.save(task);
    }

    @Override
    public PageUtils confirmTaskList(Map<String, Object> params) {
        Page<TaskServiceTask> page = new Query<TaskServiceTask>(params).getPage();
        page.setRecords(baseMapper.confirmTaskList(page, params));
        return new PageUtils(page);
    }

    @Override
    public TaskOperModel taskServiceDetail(Integer taskId) {
        TaskServiceTask task = this.getById(taskId);
        if (null == task) {
            throw new RRException("无数据");
        }
        String operDetail = task.getOperDetail();
        TaskServiceOtherModel model;
        if (StringUtils.isEmpty(operDetail)) {
            model = new TaskServiceOtherModel();
            model.setTaskId(taskId);
        } else {
            model = JSON.parseObject(operDetail, TaskServiceOtherModel.class);
        }
        model.setConfirmResult(task.getConfirmStatus());
        model.setConfirmReason(task.getConfirmReason());
        return model;
    }

    @Override
    public void tempSave(TaskOperModel model) {
        TaskServiceTask task = this.getById(model.getTaskId());
        if (null == task) {
            throw new RRException("对象不存在");
        }
        TaskServiceOtherModel otherModel = (TaskServiceOtherModel) model;
        task.setOperDetail(JSON.toJSONString(otherModel));
        this.updateById(task);
    }

    @Override
    @Transactional
    public void submitTask(TaskOperModel model) {
        TaskServiceTask task = this.getById(model.getTaskId());
        if (null == task) {
            throw new RRException("对象不存在");
        }
        boolean skipConfirm = null == model.getSkipConfirm() ? false : model.getSkipConfirm();//是否直接不用干活直接提交
        if (!skipConfirm) {
            TaskServiceOtherModel otherModel = (TaskServiceOtherModel) model;
            otherModel.setUserMain(sysUserService.getOne(new LambdaQueryWrapper<SysUserEntity>().eq(SysUserEntity::getUserId, task.getUserMainId())).getName());
            String userAssist = task.getUserAssist();
            if (StringUtils.isNotEmpty(userAssist)) {
                List<WorkUserModel> us = JSON.parseArray(userAssist, WorkUserModel.class);
                List<String> ss = us.stream().map(workUserModel -> workUserModel.getName()).collect(Collectors.toList());
                otherModel.setUserAssist(String.join(",", ss));
            }
            task.setOperDetail(JSON.toJSONString(otherModel));
        }
        task.setFinishTime(LocalDateTime.now());//完成时间设置
        task.setStatus(9);//状态设置
        //判断是否要确认，不要的话直接把确认状态改成1了
        if (task.getIfConfirm() == 0) {
            task.setConfirmStatus(1);
            task.setStatus(10);
        }
        this.updateById(task);
        //判断是否所有子任务都做完了，是的话就更新主任务的状态为9
        int count = this.count(new LambdaQueryWrapper<TaskServiceTask>().eq(TaskServiceTask::getServicePlanId, task.getServicePlanId()).ne(TaskServiceTask::getId, task.getId()).ne(TaskServiceTask::getStatus, 9));
        if (count == 0) {
            TaskServicePlan p = new TaskServicePlan();
            p.setStatus(9);
            p.setId(task.getServicePlanId());
            //如果自己是不用确认的，那就判断是否所有子任务都确认完了，是的话就更新主任务的状态为10
            if (task.getIfConfirm() == 0) {
                int countC = this.count(new LambdaQueryWrapper<TaskServiceTask>().eq(TaskServiceTask::getServicePlanId, task.getServicePlanId()).ne(TaskServiceTask::getId, task.getId()).lt(TaskServiceTask::getStatus, 10));
                if (countC == 0) {
                    p.setStatus(10);
                }
            }
            taskServicePlanService.updateById(p);
        }
        //发消息
        taskExecutor.submit(() -> {
            if (task.getIfConfirm() == 1) {
                PlanTaskModel ptm = new PlanTaskModel(task.getId(), task.getMainTaskName(), task.getName(), "", task.getTaskStartDate(), task.getUserAssistModel());

                TaskServicePlan plan = taskServicePlanService.getOne(new LambdaQueryWrapper<TaskServicePlan>().eq(TaskServicePlan::getId, task.getServicePlanId()).select(TaskServicePlan::getId, TaskServicePlan::getTaskName));
                MsgInfo msg = new MsgInfo("计划任务", "操作任务:" + plan.getTaskName(), "任务待确认", JSON.toJSONString(ptm));

                List<Integer> userIds = new ArrayList<>();
                userIds.add(task.getConfirmUser());
//                msg.setUserIdList(userIds);
                msgUserService.insertBatch(msg, userIds);
            }
        });
    }

    @Override
    @Transactional
    public void commitTask(TaskOperModel model) {
        TaskServiceTask task = this.getById(model.getTaskId());
        task.setConfirmStatus(model.getConfirmResult());
        task.setConfirmReason(model.getConfirmReason());
        task.setStatus(10);//确认完成
        //判断是不是子任务都确认完了( 除了自己以外，没有状态小于9的数据了)，是的话把主任务状态也改一下
        Integer servicePlanId = task.getServicePlanId();
        int count = this.count(new LambdaQueryWrapper<TaskServiceTask>().eq(TaskServiceTask::getServicePlanId, servicePlanId).lt(TaskServiceTask::getStatus, 10).ne(TaskServiceTask::getId, task.getId()));
        if (0 == count) {
            TaskServicePlan plan = new TaskServicePlan();
            plan.setId(servicePlanId);
            plan.setStatus(10);
            taskServicePlanService.updateById(plan);
        }
        this.updateById(task);
    }

    @Override
    public List<TaskServiceTask> shiftsList(Integer selfId) {
        return baseMapper.shiftsList(selfId);
    }

    @Override
    @Transactional
    public void start(Integer taskId) {
        TaskServiceTask task = this.getOne(new LambdaQueryWrapper<TaskServiceTask>().eq(TaskServiceTask::getId, taskId).select(TaskServiceTask::getId, TaskServiceTask::getType, TaskServiceTask::getStartTime));
        if (null == task) {
            throw new RRException("对象不存在");
        }
        if (task.getType().intValue() == 9)//如果是临时任务，那么就把计划开始时间设置成现在把
        {
            TaskServicePlan plan = taskServicePlanService.getOne(new LambdaQueryWrapper<TaskServicePlan>().eq(TaskServicePlan::getId, task.getServicePlanId()).select(TaskServicePlan::getId));
            if (null != plan) {
                plan.setPlanStartDate(LocalDateTime.now());
                taskServicePlanService.updateById(plan);
            }
        }
        task.setStartTime(LocalDateTime.now());
        this.updateById(task);
    }
}
